package manage

import (
	"sync"
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/websocket/v2"
	logger "github.com/sirupsen/logrus"
	"github.com/tidwall/gjson"

	"publish-manage/internal/model"
	"publish-manage/internal/service"
	"publish-manage/internal/ws"
	"publish-manage/pkg/constant"
	"publish-manage/pkg/server"
)

func InitRouter() {
	// 用户
	{
		server.Post("/signIn", UserController.SignIn)
		user := server.Group("/api/v1/user", server.Jwtware)
		user.Post("/", UserController.Add)
		user.Delete("/", UserController.Delete)
		user.Put("/", UserController.Update)
		user.Get("/", UserController.List)
		user.Get("/detail", UserController.Detail)
		user.Post("/pwd", UserController.UpdatePassword)
		user.Post("/resetPwd", UserController.ResetPassword)
	}
	// 应用
	{
		app := server.Group("/api/v1/application", server.Jwtware)
		app.Post("/", ApplicationController.Add)
		app.Delete("/", ApplicationController.Delete)
		app.Put("/", ApplicationController.Update)
		app.Get("/", ApplicationController.List)
	}
	// 应用部署包
	{
		pack := server.Group("/api/v1/appPackage", server.Jwtware)
		pack.Post("/", AppPackageController.Add)
		pack.Delete("/", AppPackageController.Delete)
		pack.Put("/", AppPackageController.Update)
		pack.Get("/", AppPackageController.List)
	}
	// 部署包版本管理
	{
		pv := server.Group("/api/v1/packageVersion", server.Jwtware)
		pv.Get("/instance", PackageVersionController.GetInstance)
		pv.Get("/", PackageVersionController.List)
	}
	// 进行部署动作
	{
		p := server.Group("/api/v1/publish", server.Jwtware)
		p.Post("/", PublishController.publish)
	}
	// 代理使用
	{
		server.Get("/agent/download", AgentRequestController.GetPackage)
	}

	// 启用websocket供agent连接，进行数据实时传输
	initWebsocket()
}

func initWebsocket() {
	server.Use("/ws", func(c *fiber.Ctx) error {
		if websocket.IsWebSocketUpgrade(c) {
			ip := server.GetClientIp(c)
			c.Locals("ip", ip)
			return c.Next()
		}
		return fiber.ErrUpgradeRequired
	})
	server.Get("/ws/:agentId", websocket.New(func(c *websocket.Conn) {
		conn := &ws.Conn{
			Conn:      c,
			Lock:      &sync.Mutex{},
			Deadline:  time.Now().Add(3 * time.Minute),
			CloseChan: make(chan struct{}),
			MsgChan:   make(chan []byte),
		}
		defer func() {
			conn.Close()
		}()
		defer func() {
			if err := recover(); err != nil {
				logger.Error(conn, "Websocket PANIC!!! ", err)
			}
		}()

		agentId := c.Params("agentId")
		var agent *model.Agent
		if agentId == "" {
			// 说明是新的链接
			agent = &model.Agent{
				Ip: c.Locals("ip").(string),
			}
			if existOne, err := service.AgentService.Add(agent); err != nil {
				logger.Error(err)
				ws.SendWebsocketInfo(conn, &ws.SendInfo{
					Code: constant.ResponseCodeErrorInternal,
					Msg:  "无法注册代理:" + err.Error(),
				})
				return
			} else if existOne != nil {
				// 重复了，把重复的拿出来,id发回去
				ws.SendWebsocketInfo(conn, &ws.SendInfo{
					Type: ws.TypeAgentId,
					Data: existOne.Id,
				})
				agent = existOne
			} else {
				// 添加成功
				ws.SendWebsocketInfo(conn, &ws.SendInfo{
					Type: ws.TypeAgentId,
					Data: agent.Id,
				})
			}
		} else {
			var err error
			agent, err = service.AgentService.Get(&model.Agent{Id: agentId})
			if err != nil {
				logger.Error(err)
				ws.SendWebsocketInfo(conn, &ws.SendInfo{
					Code: constant.ResponseCodeErrorInternal,
					Msg:  "无法注册代理:" + err.Error(),
				})
				return
			}
			if agent == nil {
				// 代理ID有问题，重新注册
				agent = &model.Agent{
					Ip: c.Locals("ip").(string),
				}
				var existOne *model.Agent
				if existOne, err = service.AgentService.Add(agent); err != nil {
					logger.Error(err)
					c.WriteMessage(websocket.TextMessage, []byte("无法注册代理:"+err.Error()))
					return
				} else if existOne != nil {
					// 重复了，把重复的拿出来,id发回去
					ws.SendWebsocketInfo(conn, &ws.SendInfo{
						Type: ws.TypeAgentId,
						Data: existOne.Id,
					})
					agent = existOne
				} else {
					// 添加成功
					ws.SendWebsocketInfo(conn, &ws.SendInfo{
						Type: ws.TypeAgentId,
						Data: agent.Id,
					})
				}
			} else {
				ws.SendWebsocketInfo(conn, &ws.SendInfo{
					Type: ws.TypeAgentId,
					Data: agent.Id,
				})
			}
		}
		if agent == nil {
			ws.SendWebsocketInfo(conn, &ws.SendInfo{
				Code: constant.ResponseCodeErrorInternal,
				Msg:  "代理处理失败! 无法更新代理信息",
			})
			return
		}

		// 添加到管理器
		ws.AgentManager.AddAgent(agent, conn)

		go func() {
			for {
				if mt, msg, err := c.ReadMessage(); err != nil {
					logger.Error("ws read error: ", err)
					conn.Close()
					return
				} else if mt == websocket.PingMessage {
					c.WriteMessage(websocket.PongMessage, []byte("pong"))
				} else if mt == websocket.TextMessage {
					conn.MsgChan <- msg
				} else if mt == websocket.CloseMessage {
					conn.Close()
					return
				} else {
					ws.SendWebsocketInfo(conn, &ws.SendInfo{Code: constant.ResponseCodeErrorUnsupported, Msg: "不支持的消息类型"})
				}
			}
		}()

		for {
			select {
			case <-conn.CloseChan:
				return
			case msg := <-conn.MsgChan:
				if sendInfo := dealMessage(msg, agent, conn); sendInfo != nil {
					ws.SendWebsocketInfo(conn, sendInfo)
				}
			}
		}
	}))
}

func dealMessage(msg []byte, agent *model.Agent, conn *ws.Conn) *ws.SendInfo {
	js := gjson.ParseBytes(msg)
	t := js.Get("type").Int()
	switch t {
	case ws.TypeServerInfo: //上报服务端信息
		ws.AgentManager.UpdateServerInfo(agent.Id, js.Get("data"))
		return nil
	}
	return nil
}
